﻿using Plugins;
using Plugins.Base.Common;
using Plugins.UserControls;
using TechnicalIndicators.DateBased;
using TechnicalIndicators.QuotationBased;

namespace SMAPlugin.Common
{
    internal class FastSlowCrossProcessor : IDecisionEngineStateProcessor
	{
		#region Attributes

		private readonly DecisionEngineData _data;
		private readonly HourSelectorData _hourSettings;
		private readonly LastValueGenerator _lastValueGenerator;
		private readonly MovingAverage _slowSMAGenerator;
		private readonly MovingAverage _fastSMAGenerator;
		private readonly StrategyControlData _strategySettings;
		private readonly OperationManager _operationManager;

	    #endregion

		#region Public Methods

		public FastSlowCrossProcessor(DecisionEngineData data, HourSelectorData hourSettings, MovingAverage slowSMAGenerator, MovingAverage fastSMAGenerator, LastValueGenerator lastValueGenerator, StrategyControlData strategySettings, OperationManager operationManager)
		{
			_data = data;
			_hourSettings = hourSettings;
			_lastValueGenerator = lastValueGenerator;
			_slowSMAGenerator = slowSMAGenerator;
			_fastSMAGenerator = fastSMAGenerator;
			_strategySettings = strategySettings;
			_operationManager = operationManager;
		}

        public DecisionEngineStateBase ProcessWaitingOpen()
        {
            DecisionEngineStateBase result = null;

            if (_data.LastQuotation.Date.TimeOfDay > _hourSettings.LastOpen)
            {
                result = DecisionEngineState.DayClosed;
            }
            else if (_data.LastQuotation.Volume > 0)
            {
                result = DecisionEngineState.WaitingSlowAverage;
            }

            return result;
        }

        public DecisionEngineStateBase ProcessWaitingSlowAverage()
        {
            DecisionEngineStateBase result = null;

            if (_data.LastQuotation.Date.TimeOfDay > _hourSettings.LastOpen)
            {
                result = DecisionEngineState.DayClosed;
            }
            else if (_slowSMAGenerator.LastValue != null)
            {
                if (_slowSMAGenerator.LastValue.Y < _fastSMAGenerator.LastValue.Y)
                {
                    result = DecisionEngineState.WaitingCrossDown;
                }
                else if (_slowSMAGenerator.LastValue.Y > _fastSMAGenerator.LastValue.Y)
                {
                    result = DecisionEngineState.WaitingCrossUp;
                }
            }

	        return result;
        }

        public DecisionEngineStateBase ProcessWaitingCrossUp()
        {
            DecisionEngineStateBase result = null;

            if (_data.LastQuotation.Date.TimeOfDay > _hourSettings.LastOpen)
            {
                result = DecisionEngineState.DayClosed;
            }
            else if (_slowSMAGenerator.LastValue.Y < _fastSMAGenerator.LastValue.Y && _data.LastQuotation.Sellers[0].Quantity >= _strategySettings.Volume)
            {
                _operationManager.OpenLongPossition(_strategySettings.Volume);
                result = DecisionEngineState.OnLongPossition;
            }

            return result;
        }

        public DecisionEngineStateBase ProcessWaitingCrossDown()
        {
            DecisionEngineStateBase result = null;

            if (_data.LastQuotation.Date.TimeOfDay > _hourSettings.LastOpen)
            {
                result = DecisionEngineState.DayClosed;
            }
            else if (_slowSMAGenerator.LastValue.Y > _fastSMAGenerator.LastValue.Y && _data.LastQuotation.Buyers[0].Quantity >= _strategySettings.Volume)
            {
                _operationManager.OpenShortPossition(_strategySettings.Volume);
                result = DecisionEngineState.OnShortPossition;
            }

            return result;
        }

        public DecisionEngineStateBase ProcessOnLongPossition()
        {
            DecisionEngineStateBase result = null;

            if (_data.LastQuotation.Date.TimeOfDay >= _hourSettings.ForcedCloseTime || (_slowSMAGenerator.LastValue.Y > _fastSMAGenerator.LastValue.Y || _operationManager.CurrentOperation.BuyPrice + _strategySettings.FixedWin <= _data.LastQuotation.Buyers[0].Value) && _data.LastQuotation.Buyers[0].Quantity >= _strategySettings.Volume)
            {
                _operationManager.CloseLongPossition();
                result = _slowSMAGenerator.LastValue.Y > _fastSMAGenerator.LastValue.Y ? DecisionEngineState.WaitingCrossUp : DecisionEngineState.WaitingCrossDown;
            }

            return result;
        }

        public DecisionEngineStateBase ProcessOnShortPossition()
        {
            DecisionEngineStateBase result = null;

            if (_data.LastQuotation.Date.TimeOfDay >= _hourSettings.ForcedCloseTime || (_slowSMAGenerator.LastValue.Y < _fastSMAGenerator.LastValue.Y || _operationManager.CurrentOperation.SellPrice - _strategySettings.FixedWin >= _data.LastQuotation.Sellers[0].Value) && _data.LastQuotation.Sellers[0].Quantity >= _strategySettings.Volume)
            {
                _operationManager.CloseShortPossition();
                result = _slowSMAGenerator.LastValue.Y < _fastSMAGenerator.LastValue.Y ? DecisionEngineState.WaitingCrossDown : DecisionEngineState.WaitingCrossUp;
            }

            return result;
        }

        public DecisionEngineStateBase ProcessDayClosed()
        {
            DecisionEngineStateBase result = null;

            if (_data.LastQuotation.Date.TimeOfDay < _hourSettings.LastOpen && (_data.LastQuotation.Date.Date != _data.PreviousQuotation.Date.Date || _data.LastQuotation.Date < _data.PreviousQuotation.Date))
            {
				_data.PreviousQuotation = null;

				_lastValueGenerator.Clear();
                _slowSMAGenerator.Clear();
                _fastSMAGenerator.Clear();

				_lastValueGenerator.Start();
				_slowSMAGenerator.Start();
                _fastSMAGenerator.Start();

                result = DecisionEngineState.WaitingOpen;
            }

			return result;
        }

		#endregion
	}
}
